package ae.pcfc.etks.online.itworx.ehs.web.facade.impl;

import java.net.ConnectException;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ws.client.WebServiceIOException;

import ae.pcfc.etks.online.common.vo.UserDetailVO;
import ae.pcfc.etks.online.fnp.exception.FNPException;
import ae.pcfc.etks.online.fnp.service.FNPService;
import ae.pcfc.etks.online.fnp.service.types.CancelPaymentAdviceResponse;
import ae.pcfc.etks.online.fnp.service.types.ClientType;
import ae.pcfc.etks.online.fnp.service.types.GeneratePaymentAdviceResponse;
import ae.pcfc.etks.online.fnp.service.types.GetServiceCatalogueResponse.Service;
import ae.pcfc.etks.online.fnp.service.types.GetServiceParametersResponse;
import ae.pcfc.etks.online.fnp.service.types.ServiceParameterType;
import ae.pcfc.etks.online.fnp.service.types.ServicePaymentRequestType;
import ae.pcfc.etks.online.fnp.service.vo.ExtraParametersVO;
import ae.pcfc.etks.online.itworx.ehs.web.constants.GlobalConstants;
import ae.pcfc.etks.online.itworx.ehs.web.exception.CommunicationException;
import ae.pcfc.etks.online.itworx.ehs.web.exception.FNPServiceExpcetion;
import ae.pcfc.etks.online.itworx.ehs.web.facade.FNPFacade;
import ae.pcfc.etks.online.itworx.ehs.web.manager.FNPManager;
import ae.pcfc.etks.online.itworx.ehs.web.model.FNP;
import ae.pcfc.etks.online.itworx.ehs.web.model.FNPFeesParameter;
import ae.pcfc.etks.online.itworx.ehs.web.model.FNPFeesService;
import ae.pcfc.etks.online.itworx.ehs.web.model.PaymentAdvice;

public class FNPFacadeImpl extends BaseFacade implements FNPFacade {

	private FNPManager fnpManager;
	private FNPService fnpService;

	private Logger log = LoggerFactory.getLogger(FNPFacadeImpl.class);

	public FNPManager getFnpManager() {
		return fnpManager;
	}

	public void setFnpManager(FNPManager fnpManager) {
		this.fnpManager = fnpManager;
	}

	public FNPService getFnpService() {
		return fnpService;
	}

	public void setFnpService(FNPService fnpService) {
		this.fnpService = fnpService;
	}

	@Override
	public List<FNPFeesService> getServices() throws CommunicationException,
			FNPServiceExpcetion {
		try {

			List<FNPFeesService> fnpAllServices = new ArrayList<FNPFeesService>();
			List<Service> services = fnpService.getServiceCatalogue(
					GlobalConstants.FNP_EHS_ONLINE_SOURCE_ID,
					GlobalConstants.FNP_GET_SERVICE_CATALOGUE_ALL);

			for (Service service : services) {
				FNPFeesService fnpservice = new FNPFeesService();
				fnpservice.setServiceId(service.getId());
				fnpservice.setServiceCode(service.getCode());
				fnpservice.setEnglishName(service.getDescriptionEn());
				fnpservice.setArabicName(service.getDescriptionAr());
				fnpAllServices.add(fnpservice);
			}

			return fnpAllServices;
		} catch (FNPException fnpException) {
			log.error(
					"FNPFacadeImpl.getServices() - FNP Exception error happned while getting FNP Fees Services",
					fnpException);

			FNPServiceExpcetion fnpServiceExp = new FNPServiceExpcetion(
					fnpException);
			fnpServiceExp.setErrorCode("error.fnp.unexpected");
			throw fnpServiceExp;
		}

		// TODO check this ! catch connect exp. in fnp instead
		catch (ConnectException connectExp) {
			log.error(
					"FNPFacadeImpl.getServices() - error happned while getting FNP Fees Services",
					connectExp);
			CommunicationException communicationExp = new CommunicationException(
					connectExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}

		catch (WebServiceIOException wsIOExp) {
			log.error(
					"FNPFacadeImpl.getServices() - error happned while getting FNP Fees Services",
					wsIOExp);
			CommunicationException communicationExp = new CommunicationException(
					wsIOExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}
	}

	@Override
	public List<FNPFeesService> getServiceInfoAndParameters(
			List<String> servicesId) throws CommunicationException,
			FNPServiceExpcetion {
		try {

			List<GetServiceParametersResponse.Service> services = fnpService
					.getServiceInfoAndParameters(servicesId,
							GlobalConstants.FNP_EHS_ONLINE_SOURCE_ID);
			List<FNPFeesService> fnpServices = new ArrayList<FNPFeesService>();

			for (GetServiceParametersResponse.Service service : services) {
				FNPFeesService fnpService = new FNPFeesService();
				fnpService.setServiceId(service.getServiceId());

				if (service.getServiceParameter().isEmpty()) {
					FNPFeesParameter fnpParameter = new FNPFeesParameter();
					fnpParameter.setServiceId(service.getServiceId());
					fnpParameter.setDummy(true);
					fnpParameter.setName("name");
					fnpService.getFnpParameters().add(fnpParameter);
				} else {
					for (ServiceParameterType parameter : service
							.getServiceParameter()) {
						FNPFeesParameter fnpParameter = new FNPFeesParameter();
						fnpParameter.setServiceId(service.getServiceId());
						fnpParameter.setName(parameter.getName());
						fnpParameter.setArabicName(parameter.getName());
						fnpParameter.setEnglishName(parameter.getName());
						fnpParameter.setOrder(parameter.getOrder());

						fnpService.getFnpParameters().add(fnpParameter);
					}
				}
				fnpServices.add(fnpService);
			}

			return fnpServices;
		}

		catch (FNPException fnpExp) {
			log.error(
					"FNPFacadeImpl.getServiceInfoAndParameters() - FNP Exception error happned while getting FNP Fees Services and its parameters for services ("
							+ servicesId + ")", fnpExp);

			FNPServiceExpcetion fnpServiceExp = new FNPServiceExpcetion(fnpExp);
			fnpServiceExp.setErrorCode("error.fnp.unexpected");
			throw fnpServiceExp;
		}

		catch (ConnectException connectExp) {
			log.error(
					"FNPFacadeImpl.getServiceInfoAndParameters() - error happned while getting FNP Fees Services and its parameters for services ("
							+ servicesId + ")", connectExp);
			CommunicationException communicationExp = new CommunicationException(
					connectExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}

		catch (WebServiceIOException wsIOExp) {
			log.error(
					"FNPFacadeImpl.getServices() - error happned while getting FNP Fees Services",
					wsIOExp);
			CommunicationException communicationExp = new CommunicationException(
					wsIOExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}
	}

	public Double previewPaymentAdvice(FNP fnpModel, UserDetailVO userDetails)
			throws CommunicationException, FNPServiceExpcetion {

		try {
			List<ServicePaymentRequestType> rawServices = new ArrayList<ServicePaymentRequestType>();

			for (FNPFeesService service : fnpModel.getFnpServices()) {
				ServicePaymentRequestType paymentServiceRequest = new ServicePaymentRequestType();
				paymentServiceRequest.setId(service.getServiceId());
				if (service.getQuantity() < 1) {
					paymentServiceRequest.setQuantity(1);
				} else {
					paymentServiceRequest.setQuantity(service.getQuantity());
				}

				for (FNPFeesParameter parameter : service.getFnpParameters()) {
					if (!parameter.isDummy()) {
						ServiceParameterType serviceParameterType = new ServiceParameterType();
						serviceParameterType.setName(parameter.getName());
						serviceParameterType.setOrder(parameter.getOrder());
						serviceParameterType.setValue(String.valueOf(parameter
								.getValue()));

						paymentServiceRequest.getServiceParameter().add(
								serviceParameterType);
					}
				}

				rawServices.add(paymentServiceRequest);
			}

			ClientType clientType = new ClientType();
			clientType.setId(userDetails.getTrakheesId());
			clientType.setNameAr(userDetails.getCompanyVO().getStrNameARB());
			clientType.setNameEn(userDetails.getCompanyVO().getStrNameENG());
			clientType.setLicenseNumber(userDetails.getCompanyVO()
					.getStrLicenseNumber());

			return fnpService.previewPaymentAdvice(clientType,
					fnpModel.getExpiryDate(), fnpModel.getRemarks(),
					rawServices, GlobalConstants.FNP_EHS_ONLINE_SOURCE_ID);
		} catch (ConnectException connectExp) {
			log.error(
					"FNPFacadeImpl.previewPaymentAdvice() - error happned while previewing FNP Payment Advice",
					connectExp);
			CommunicationException communicationExp = new CommunicationException(
					connectExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}

		catch (FNPException fnpExp) {
			FNPServiceExpcetion fnpServiceExp = new FNPServiceExpcetion(fnpExp);
			fnpServiceExp.setErrorCode("error.fnp.unexpected");
			throw fnpServiceExp;
		}

		catch (WebServiceIOException wsIOExp) {
			log.error(
					"FNPFacadeImpl.getServices() - error happned while getting FNP Fees Services",
					wsIOExp);
			CommunicationException communicationExp = new CommunicationException(
					wsIOExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}

	}

	@Override
	public PaymentAdvice generatePaymentAdvice(FNP fnpModel, String userName,
			String transactionNumber, UserDetailVO userDetails)
			throws CommunicationException, FNPServiceExpcetion {
		try {
			List<ServicePaymentRequestType> services = new ArrayList<ServicePaymentRequestType>();
			ClientType client = new ClientType();
			PaymentAdvice paymentAdvice = new PaymentAdvice();

			client.setId(userDetails.getTrakheesId());
			client.setNameAr(userDetails.getCompanyVO().getStrNameARB());
			client.setNameEn(userDetails.getCompanyVO().getStrNameENG());
			client.setLicenseNumber(userDetails.getCompanyVO()
					.getStrLicenseNumber());

			for (FNPFeesService service : fnpModel.getFnpServices()) {
				ServicePaymentRequestType paymentServiceRequest = new ServicePaymentRequestType();
				paymentServiceRequest.setId(service.getServiceId());
				if (service.getQuantity() < 1) {
					paymentServiceRequest.setQuantity(1);
				} else {
					paymentServiceRequest.setQuantity(service.getQuantity());
				}

				for (FNPFeesParameter parameter : service.getFnpParameters()) {
					if (!parameter.isDummy()) {
						ServiceParameterType serviceParameterType = new ServiceParameterType();
						serviceParameterType.setName(parameter.getName());
						serviceParameterType.setOrder(parameter.getOrder());
						serviceParameterType.setValue(String.valueOf(parameter
								.getValue()));

						paymentServiceRequest.getServiceParameter().add(
								serviceParameterType);
					}
				}

				services.add(paymentServiceRequest);
			}

			ExtraParametersVO extraParam = new ExtraParametersVO();

			extraParam.setTransactionNumber(transactionNumber);
			extraParam.setUserName(userName);
			GeneratePaymentAdviceResponse fnpPaymentAdvice = null;

			fnpPaymentAdvice = fnpService.generatePaymentAdvice(client,
					fnpModel.getExpiryDate(), fnpModel.getRemarks(),
					fnpModel.getRemarks(), extraParam, services,
					GlobalConstants.FNP_EHS_ONLINE_SOURCE_ID);

			if (null != fnpPaymentAdvice) {
				paymentAdvice.setPaymentAdviceNumber(fnpPaymentAdvice
						.getPaymentAdviceNumber());
				paymentAdvice.setPaymentfees(fnpPaymentAdvice
						.getPaymentAdviceAmount());
				paymentAdvice.setFile(fnpPaymentAdvice.getPaymentAdvicePDF());
			}

			return paymentAdvice;
		}

		catch (ConnectException connectExp) {
			log.error(
					"FNPFacadeImpl.generatePaymentAdvice() - error happned while generating FNP Payment Advice",
					connectExp);
			CommunicationException communicationExp = new CommunicationException(
					connectExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}

		catch (FNPException fnpExp) {
			FNPServiceExpcetion fnpServiceExp = new FNPServiceExpcetion(fnpExp);
			fnpServiceExp.setErrorCode("error.fnp.unexpected");
			throw fnpServiceExp;
		}

		catch (WebServiceIOException wsIOExp) {
			log.error(
					"FNPFacadeImpl.getServices() - error happned while getting FNP Fees Services",
					wsIOExp);
			CommunicationException communicationExp = new CommunicationException(
					wsIOExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}
	}

	@Override
	public String queryPaymentAdviceStatus(String paymentAdviceNumber)
			throws CommunicationException, FNPServiceExpcetion {
		try {
			return fnpService.queryPaymentAdviceStatus(paymentAdviceNumber,
					GlobalConstants.FNP_EHS_ONLINE_SOURCE_ID);
		} catch (ConnectException connectExp) {
			log.error(
					"FNPFacadeImpl.queryPaymentAdviceStatus() - error happned while querying FNP Payment Advice Status",
					connectExp);
			CommunicationException communicationExp = new CommunicationException(
					connectExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}

		catch (FNPException fnpExp) {
			FNPServiceExpcetion fnpServiceExp = new FNPServiceExpcetion(fnpExp);
			fnpServiceExp.setErrorCode("error.fnp.unexpected");
			throw fnpServiceExp;
		}

		catch (WebServiceIOException wsIOExp) {
			log.error(
					"FNPFacadeImpl.getServices() - error happned while getting FNP Fees Services",
					wsIOExp);
			CommunicationException communicationExp = new CommunicationException(
					wsIOExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}
	}

	@Override
	public CancelPaymentAdviceResponse cancelPaymentAdvice(
			String transactionNumber, String paymentAdviceNumber,
			String userName, String message) throws CommunicationException,
			FNPServiceExpcetion {
		try {
			return fnpService.cancelPaymentAdvice(transactionNumber,
					paymentAdviceNumber, userName, message,
					GlobalConstants.FNP_EHS_ONLINE_SOURCE_ID);
		}

		catch (FNPException fnpExp) {
			FNPServiceExpcetion fnpServiceExp = new FNPServiceExpcetion(fnpExp);
			fnpServiceExp.setErrorCode("error.fnp.unexpected");
			throw fnpServiceExp;
		}

		catch (ConnectException connectExp) {
			log.error(
					"FNPFacadeImpl.cancelPaymentAdvice() - error happned while canceling FNP Payment Advice",
					connectExp);
			CommunicationException communicationExp = new CommunicationException(
					connectExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}

		catch (WebServiceIOException wsIOExp) {
			log.error(
					"FNPFacadeImpl.getServices() - error happned while getting FNP Fees Services",
					wsIOExp);
			CommunicationException communicationExp = new CommunicationException(
					wsIOExp);
			communicationExp.setErrorCode("error.fnp.communication");
			throw communicationExp;
		}
	}
}
